package fr.utt.lo02.CrazyEights.model.players;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Observable;

/**
 * A class storing the list of players.
 * 
 * @author Jeremy
 * 
 */

public class PlayersList extends Observable implements Serializable{

	private static final long serialVersionUID = 1L;

	/**
	 * The players list
	 */
	private ArrayList<Player> players;
	
	/**
	 * The max number of players
	 */
	private final int nbMaxOfPlayers = 8;
	
	/**
	 * The actual position in the players list
	 */
	private int position = 0;
	
	/**
	 * The direction of the game
	 */
	private boolean clockwise = true;
	
	/**
	 * The rounds played by each player
	 */
	private HashMap<Player,Integer> roundsPlayed = new HashMap<Player,Integer>();
	
	public PlayersList() {
		players = new ArrayList<Player>();
	}
	
	/**
	 * Add a non human player
	 * @param name name wanted for the player
	 */
	public void addPlayer(String name){
		addPlayer(name, false);
	}
	
	/**
	 * Add a player
	 * @param name name wanted for the player
	 * @param human status of the player. True if human, false otherwise
	 */
	public void addPlayer(String name, boolean human) {
			if(players.size() < nbMaxOfPlayers) {
				if(human)
					players.add(new Human(name));
				else
					players.add(new AI(name));
				
				roundsPlayed.put(players.get(players.size()-1), 0);
				
			}
	}
	
	/**
	 * 
	 * @return the current player
	 */
	public Player getCurrentPlayer(){
		if(position>=0 && position<players.size())
			return players.get(position);
		else
			return null;
	}
	
	/**
	 * 
	 * @return the previous player
	 */
	public Player getPreviousPlayer(){
		Player previousPlayer;
		if(clockwise){
			if(position>0){
				previousPlayer = players.get(position-1);
			}else{
				previousPlayer = players.get(players.size()-1);
			}
		}else{
			if(position<players.size()-1){
				previousPlayer = players.get(position+1);
			}else{
				previousPlayer = players.get(0);
			}
		}
		return previousPlayer;
	}
	
	/**
	 * change the current player to the next one
	 */
	public void nextPlayer(){
		if(clockwise){
			if(position < players.size()-1)
				position++;
			else
				position=0;
		}else{
			if(position > 0)
				position--;
			else
				position=players.size()-1;
		}
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Skip the next player
	 */
	public void skipNextPlayer(){
		this.nextPlayer();
		this.nextPlayer();
	}
	
	/**
	 * 
	 * @return the next player
	 */
	public Player getNextPlayer(){
		Player nextPlayer;
		if(clockwise){
			if(position < players.size()-1)
				nextPlayer = players.get(position+1);
			else
				nextPlayer = players.get(0);
		}else{
			if(position > 0)
				nextPlayer = players.get(position-1);
			else
				nextPlayer = players.get(players.size()-1);
		}
		return nextPlayer;
	}
	
	/**
	 * Change the direction of the game
	 */
	public void changeDirection(){
		if(clockwise)
			clockwise=false;
		else
			clockwise=true;
	}
	
	public ArrayList<Player> getPlayersList() {
		return players;
	}
	
	public int size(){
		return players.size();
	}
	
	/**
	 * Add a round played for the given player
	 * @param p the player which we add a round played
	 */
	public void addPlayed(Player p){
		roundsPlayed.put(p,roundsPlayed.get(p)+1);
	}
	
	/**
	 * 
	 * @return the number of ended rounds
	 */
	public int getNbOfEndedRounds(){
		int nbOfEndedRounds = 0;
		if(!players.isEmpty()){
			nbOfEndedRounds = roundsPlayed.get(players.get(0));
		}
		for(Player p : players){
			if(roundsPlayed.get(p)<nbOfEndedRounds){
				nbOfEndedRounds = roundsPlayed.get(p);
			}
		}
		return nbOfEndedRounds;
	}
	
	/**
	 * Create the ranking and return it
	 * @return the ranking
	 */
	public ArrayList<Player> getRanking(){
		ArrayList<Player> ranking = new ArrayList<Player>();
		ArrayList<Integer> points = new ArrayList<Integer>();
		for(Player p : players){
			points.add(p.getPoints());
		}
		Collections.sort(points);
		for(int po : points){
			for(Player p : players){
				if(p.getPoints()==po && ranking.indexOf(p)==-1){
					ranking.add(p);
				}
			}
		}
		return ranking;
	}
}
